#include "mainwindow.h"

#include <QDateTime>
#include <QDebug>
#include <QMessageBox>
#include <QThread>

#include "datasave.h"
#include "serthread.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);

    // 1.创建子线程对象，动态分配空间，指定父对象
    t_ser = new QThread(this);
    // 2.创建任务类对象,动态分配空间，不能指定父对象
    m_ser_work = new SerThread;  // 防止内存泄漏,关闭窗口时 delete m_work;
    // 3.将任务对象移动到某个子线程中
    m_ser_work->moveToThread(t_ser);

    t_datasave = new QThread(this);

    m_save_work = new DataSave;

    m_save_work->moveToThread(t_datasave);

    getportInfo();

    initSerialInfo();

    // 传递串口配置参数到线程的信号与槽
    connect(this, &MainWindow::sig_SendSerialConfig, m_ser_work, &SerThread::do_RecvSerialConfig);
    // 打开串口的信号和槽
    connect(this, &MainWindow::sig_OpenSerial, m_ser_work, &SerThread::do_OpenSerial);

    connect(this, &MainWindow::sig_isCloseSerial, m_ser_work, &SerThread::do_CloseSerial);

    connect(m_ser_work, &SerThread::sig_SetInfo, this, [=](QString info) {
        ui->statusbar->showMessage(info);
        ui->checkBox_save_file->setEnabled(true);
        ui->checkBox_stamp->setEnabled(true);
    });

    // 打开失败
    connect(m_ser_work, &SerThread::sig_noSerialOpen, this, [=]() {
        message("comPort is not exist or is opening");
        ui->pushButton_close_ser->setEnabled(false);
        ui->pushButton_open_ser->setEnabled(true);
        SetUiEnable(true);
        ui->statusbar->showMessage("");
    });

    connect(m_ser_work, &SerThread::sig_isRecvData, this, [=](QByteArray data) {
        ui->plainTextEdit_rcv->moveCursor(QTextCursor::End);
        if (hexrxFlag == true) {
            if (timeFlag == true) {
                // currentDateTime() 可以获取当前系统时间
                QDateTime time = QDateTime::currentDateTime();
                // 将时间对面按照一定的格式转换为字符串对象
                QString str = time.toString("[hh:mm:ss.zzz]");
                ui->plainTextEdit_rcv->moveCursor(QTextCursor::End);
                ui->plainTextEdit_rcv->insertPlainText(str);
            }
            ui->plainTextEdit_rcv->insertPlainText(data.toHex(' ').toUpper());
            ui->plainTextEdit_rcv->insertPlainText(" ");
            if (awFlag == true) {
                ui->plainTextEdit_rcv->moveCursor(QTextCursor::End);
                ui->plainTextEdit_rcv->insertPlainText("\n");
            }
        } else {
            if (timeFlag == true) {
                // currentDateTime() 可以获取当前系统时间
                QDateTime time = QDateTime::currentDateTime();
                // 将时间对面按照一定的格式转换为字符串对象
                QString str = time.toString("[hh:mm:ss.zzz]");
                ui->plainTextEdit_rcv->moveCursor(QTextCursor::End);
                ui->plainTextEdit_rcv->insertPlainText(str);
            }
            ui->plainTextEdit_rcv->insertPlainText(data);
            if (awFlag == true) {
                ui->plainTextEdit_rcv->moveCursor(QTextCursor::End);
                ui->plainTextEdit_rcv->insertPlainText("\n");
            }
            // data = GetCodeType(data, info->Encode);
        }
    });

    connect(m_ser_work, &SerThread::sig_isRecvData, m_save_work, &DataSave::do_rcv_save);

    connect(this, &MainWindow::sig_save_file, m_save_work, &DataSave::do_setSaveFlag);

    connect(this, &MainWindow::sig_close_file, m_save_work, &DataSave::do_CloseFile);

    connect(this, &MainWindow::sig_save_stamp, m_save_work, &DataSave::do_setStampFlag);

    qDebug() << "GUI的线程的线程地址: " << QThread::currentThread();
    // 当按窗口右上角X时，窗口触发destroyed()，析构子线程。
    connect(this, &MainWindow::destroyed, this, &MainWindow::SerStop);

    connect(this, &MainWindow::sig_isSendData, m_ser_work, &SerThread::SendData);
}

MainWindow::~MainWindow() {
    SerStop();
    FileStop();
    delete ui;
    delete info;
    delete[] comInfo;
    delete aIntValidator;
    delete m_ser_work;
    delete m_save_work;
}

void MainWindow::SetUiEnable(bool flag) {
    ui->comboBox_baud->setEnabled(flag);
    ui->comboBox_data_bits->setEnabled(flag);
    ui->comboBox_parity->setEnabled(flag);
    ui->comboBox_select_ser->setEnabled(flag);
    ui->comboBox_stop_bits->setEnabled(flag);
    ui->pushButton_get_ser->setEnabled(flag);
}

void MainWindow::message(const char* str) {
    // QMessageBox msgBox;
    // msgBox.setText(tr(str));
    // msgBox.setWindowTitle(tr("Qt上位机V0.0.1"));
    // msgBox.setWindowIcon(QIcon(":/image/image/main.ico"));
    // msgBox.exec();
    QMessageBox::warning(this, "warrning", str);
}

void MainWindow::getportInfo() {
    qint32 comCnt = 0;
    // 要删除原有的内存空间
    if (comInfo != nullptr) {
        delete[] comInfo;
    }
    if (portStringList.length() != 0) {
        portStringList.clear();
        qDebug() << "portStringList is clear";
    }
    if (ui->comboBox_select_ser->count() != 0) {
        ui->comboBox_select_ser->clear();
        qDebug() << "ui->comPortName is clear";
    }
    // 获取串口设备数量
    comCnt = QSerialPortInfo::availablePorts().length();
    if (comCnt != 0) {
        comInfo = new ScomInfo[comCnt];  // 动态分配空间,防止内存泄漏,关闭窗口时 delete [] comInfo;
        // 获取串口信息
        portNum = 0;
        foreach (const QSerialPortInfo& qspinfo, QSerialPortInfo::availablePorts()) {
            //                portStringList.clear();
            this->comInfo[portNum].SerialName = qspinfo.portName();
            //                this->comInfo[portNum].ProductCode=qspinfo.productIdentifier();
            //                this->comInfo[portNum].SystemPosition=qspinfo.systemLocation();
            //                this->comInfo[portNum].SerialNumStr=qspinfo.serialNumber();
            this->comInfo[portNum].DescribeStr = qspinfo.description();
            //                this->comInfo[portNum].Manufacturer=qspinfo.manufacturer();
            //                this->comInfo[portNum].SupplierCode=qspinfo.vendorIdentifier();
            portStringList += qspinfo.portName();
            ui->plainTextEdit_rcv->appendPlainText(qspinfo.portName() + " " + qspinfo.description());
            portNum++;
        }
        ui->comboBox_select_ser->addItems(portStringList);
        ui->plainTextEdit_rcv->appendPlainText("=============================================");
    } else {
        message("未检测到串口!");
    }
}

void MainWindow::initSerialInfo() {
    this->aIntValidator = new QIntValidator;  // 防止内存泄漏,关闭窗口时 delete aIntValidator;
    // 限制波特率输入框输入范围，且只能输入数组
    this->aIntValidator->setRange(0, 1000000);
    ui->comboBox_baud->setValidator(aIntValidator);

    // 先删除原本的内存空间if(info != nullptr)
    { delete info; }
    // 防止内存泄漏，关闭窗口时delete info
    this->info = new Sinfo;
    // 设置串口号
    this->info->comName = ui->comboBox_select_ser->currentText();
    // 波特率
    this->info->baudRate = ui->comboBox_baud->currentText().toInt();
    this->info->dataBits = ui->comboBox_data_bits->currentIndex();
    this->info->parity = ui->comboBox_parity->currentIndex();
    this->info->stopBits = ui->comboBox_stop_bits->currentIndex();
    this->info->flowControl = 0;  // 默认为0无流控
    // TODO: 目前没有流控和编码格式选择
    this->info->Encode = 0;
}

void MainWindow::SerialClose(void) {
    ui->pushButton_open_ser->setEnabled(true);
    ui->pushButton_close_ser->setEnabled(false);
    ui->checkBox_save_file->setEnabled(false);
    ui->checkBox_stamp->setEnabled(false);
    ui->checkBox_save_file->setChecked(false);
    ui->checkBox_stamp->setChecked(false);
    SetUiEnable(true);
    qDebug() << "serial close";
    emit sig_isCloseSerial();
}

void MainWindow::SerStop() {
    t_ser->quit();
    t_ser->wait();
}

void MainWindow::FileStop() {
    t_datasave->quit();
    t_datasave->wait();
}

void MainWindow::on_pushButton_get_ser_clicked() {
    qDebug() << "on_pushButton_get_ser_clicked";
    getportInfo();
}

void MainWindow::on_pushButton_open_ser_clicked() {
    qDebug() << "on_pushButton_open_ser_clicked";
    ui->pushButton_open_ser->setEnabled(false);
    ui->pushButton_close_ser->setEnabled(true);
    SetUiEnable(false);
    qDebug() << "准备打开串口";
    initSerialInfo();
    emit sig_SendSerialConfig(info);
    emit sig_OpenSerial();
    t_ser->start();
}

void MainWindow::on_pushButton_close_ser_clicked() {
    qDebug() << "on_pushButton_close_ser_clicked";
    SerialClose();
}

void MainWindow::on_pushButton_test_clicked() {
    qDebug() << "on_pushButton_test_clicked";
    // currentDateTime() 可以获取当前系统时间
    QDateTime time = QDateTime::currentDateTime();
    // 将时间对面按照一定的格式转换为字符串对象
    QString str = time.toString("[yy-MM-dd hh:mm:ss.zzz]");
    qDebug() << str;
}

void MainWindow::on_pushButton_send_ser_clicked() {
    qDebug() << "on_pushButton_send_ser_clicked";
    QString str = ui->plainTextEdit_send_ser->toPlainText();
    if (ui->checkBox_lineEnd->isChecked()) {
        str = str + "\r\n";
    }
    qDebug() << str;
    QByteArray send_data = str.toUtf8();
    emit sig_isSendData(send_data, false);
}

void MainWindow::on_pushButton_clean_clicked() {
    qDebug() << "on_pushButton_clean_clicked";
    ui->plainTextEdit_rcv->clear();
}

void MainWindow::on_checkBox_lineEnd_stateChanged(int arg1) {
    switch (arg1) {
        case Qt::Checked: qDebug() << "Checked"; break;
        case Qt::Unchecked: qDebug() << "Unchecked"; break;
        case Qt::PartiallyChecked: qDebug() << "PartiallyChecked"; break;
        default: qDebug() << "default"; break;
    }
}

void MainWindow::on_checkBox_save_file_stateChanged(int arg1) {
    switch (arg1) {
        case Qt::Checked:
            qDebug() << "Checked";
            emit sig_save_file(true);

            t_datasave->start();
            break;
        case Qt::Unchecked:
            qDebug() << "Unchecked";
            emit sig_close_file();
            break;
        case Qt::PartiallyChecked: qDebug() << "PartiallyChecked"; break;
        default: qDebug() << "default"; break;
    }
}

void MainWindow::on_checkBox_hexSend_stateChanged(int arg1) {
    // TODO: 16进制发送没有完成
    switch (arg1) {
        case Qt::Checked: qDebug() << "Checked"; break;
        case Qt::Unchecked: qDebug() << "Unchecked"; break;
        case Qt::PartiallyChecked: qDebug() << "PartiallyChecked"; break;
        default: qDebug() << "default"; break;
    }
}

void MainWindow::on_checkBox_stamp_stateChanged(int arg1) {
    switch (arg1) {
        case Qt::Checked:
            qDebug() << "Checked";
            timeFlag = true;
            awFlag = true;
            emit sig_save_stamp(true);
            break;
        case Qt::Unchecked:
            qDebug() << "Unchecked";
            timeFlag = false;
            awFlag = false;
            emit sig_save_stamp(false);
            break;
        case Qt::PartiallyChecked: qDebug() << "PartiallyChecked"; break;
        default: qDebug() << "default"; break;
    }
}

void MainWindow::on_checkBox_hex_stateChanged(int arg1) {
    switch (arg1) {
        case Qt::Checked:
            qDebug() << "Checked";
            hexrxFlag = true;
            break;
        case Qt::Unchecked:
            qDebug() << "Unchecked";
            hexrxFlag = false;
            break;
        case Qt::PartiallyChecked: qDebug() << "PartiallyChecked"; break;
        default: qDebug() << "default"; break;
    }
}
